#source("http://lu-library.googlecode.com/svn/trunk/evaluation.r")
ap <- function(prediction) {
	#prediction is a two column matrix. The first one is the true label and the second one is the prediction value
	result = 0
	sidx = sample(1:nrow(prediction))	#shuffle the list
	prediction = prediction[sidx,]
	ranklist <- prediction[sort(prediction[,2],decreasing=TRUE, index.return=TRUE)$ix,]
	numpos <- length(which(ranklist[,1]==1))
	deltaRecall <- 1/numpos
	pcount <- 0
		
	for(i in 1:nrow(ranklist)) {
		if(ranklist[i,1] == 1) {
			pcount <- pcount + 1
			precision <- pcount/i
			result <- result + precision*deltaRecall
		}
	}
	return(result)
}


precision_at_N <- function(prediction, N=20) {
	ranklist <- prediction[sort(prediction[,2],decreasing=TRUE, index.return=TRUE)$ix[1:N],]
	p_at_n = length(which(ranklist[,1]==1))/N
	return(p_at_n)
}

#reciprocal rank
reciprocal_rank <- function(prediction, N=20) {
	ranklist <- prediction[sort(prediction[,2],decreasing=TRUE, index.return=TRUE)$ix,]
	rr = 1/min(which(ranklist[,1]==1))
	return(rr)
}

ap_at_N <- function(prediction, N=20) {
	#average precision at N
	result = 0
	ranklist <- prediction[sort(prediction[,2],decreasing=TRUE, index.return=TRUE)$ix,]
	numpos <- length(which(ranklist[,1]==1))
	numpos <- min(N, numpos)
	deltaRecall <- 1/numpos
	pcount <- 0
		
	for(i in 1:(min(nrow(ranklist),N))) {
		if(ranklist[i,1] == 1) {
			pcount <- pcount + 1
			precision <- pcount/i
			result <- result + precision*deltaRecall
		}
	}
	return(result)
}


evaluate.map <- function(predictions, labels) {
	#predictions are the prediction matrix each row is a sample and each column is a class
	#labels are the same size matrix of labels
	map <- replicate(ncol(predictions), 0)
	for(eventid in 1: length(map)) {
		map[eventid] = ap(cbind(labels[,eventid], predictions[,eventid]))
	}
	return(map)
}


randomMAP <- function(numpos, numneg, randcnt = 20, binary = TRUE) {
	map <- 0
	for(i in 1:randcnt) {
		if(!binary) {
			prediction <- matrix(0,(numpos+numneg),2)
			prediction[,2] <- runif(numpos+numneg)
			prediction[sample(1:nrow(prediction),numpos),1] <- 1
			map = map + ap(prediction)
		} else {
			prediction <- matrix(0,(numpos+numneg),2)
			prediction[,2] <- sample(c(0,1),numpos+numneg, replace=TRUE)
			prediction[sample(1:nrow(prediction),numpos),1] <- 1
			map = map + ap(prediction)
		}
	}
	map = map/randcnt
	return(map)
}
